/**
 * @file test_entry.cc
 * @author enic (errorcpp@qq.com)
 * @brief 
 * @version 0.1
 * @date 2021-12-08
 * 
 * @copyright Copyright (c) 2021
 * 
 */

#include <iostream>
#include <thread>
#include <uv.h>

// libuv源码分析 https://zhuanlan.zhihu.com/c_1094553212761309184

// 如果自己封装socket参考：https://github.com/caozhiyi/CppNet/blob/master/cppnet/socket/rw_socket.h
// 他还有配套的rpc：https://github.com/caozhiyi/CppRPC

// asio的优秀封装：https://github.com/zhllxt/asio2

// 中文文档：https://www.cnblogs.com/sherlock-lin/p/14366073.html
// https://github.com/robinfoxnan/uv-rpc/blob/main/src/EventLoop.cpp

// 轻量级的lua服务器框架
// https://github.com/sniper00/moon
// 配套的ecs框架
// https://github.com/sniper00/entitas-lua
// 时间轮
// https://github.com/sniper00/timer
// lua热更新
// https://github.com/sniper00/luareload
// lua多线程
// https://github.com/sniper00/ltask
// luaprotobuf
// https://github.com/sniper00/lua-protobuf
// mysql驱动
// https://github.com/sniper00/lua-mysql
// 支持协程的lua定时器
// https://github.com/sniper00/lua_timer
// luabind
// https://github.com/Oberon00/luabind

// cmake-demo一条路
// https://github.com/ttroy50/cmake-examples

// !!! Kirigami UI Framework这是一套客户端框架，里边有多语言方案
// 可以从 https://github.com/Cuperino/QPrompt 入手来研究

enum UvRunMode : uint32_t
{
    kUvRunDefault = UV_RUN_DEFAULT,
    kUvRunOnce = UV_RUN_ONCE,
    kUvRun = UV_RUN_NOWAIT,
};

/**
 * @brief 
 *  libuv里边类似的组件叫threadpool,可能是在更高程度的抽象，我还是简单的理解为队列
 */
class ThreadEventQueue;

void fib(uv_work_t *req) {
    std::cout << "thread_id=" << std::this_thread::get_id() << "," << __FUNCTION__ << std::endl;
}

void after_fib(uv_work_t *req, int status) {
    std::cout << "thread_id=" << std::this_thread::get_id() << "," << __FUNCTION__ << std::endl;
}
void async_callback(uv_async_t* handle) {
    std::cout << "thread_id=" << std::this_thread::get_id() << "," << __FUNCTION__ << std::endl;
    // 唤醒loop
    uv_async_send(handle);
    // 关闭通道，handle loop中的活跃handle-1
    uv_close((uv_handle_t*)handle, NULL);
}
class UvEventLoop
{
public:
    UvEventLoop()
    {
        memset(&_uv_loop, 0, sizeof(_uv_loop));
    }
    void create()
    {
        uv_loop_t* def_loop = uv_default_loop();
//         typedef enum {
//   UV_LOOP_BLOCK_SIGNAL = 0,
//   UV_METRICS_IDLE_TIME
// } uv_loop_option;
        //uv_loop_configure(def_loop, )
        //uv_loop_close(def_loop);
         //uv_loop_new()
        uv_loop_init(&_uv_loop);
    }
    void run()
    {
        std::thread other_thread([this]() {
            //std::this_thread::sleep_for(std::chrono::seconds(3));
            uv_async_t* uv_async = new uv_async_t;
            memset(uv_async, NULL, sizeof(uv_async_t));
            // 创建一个给loop发送async的通道
            uv_async_init(&_uv_loop, uv_async, async_callback);
            // 唤醒loop
            uv_async_send(uv_async);
            std::cout << "thread_id=" << std::this_thread::get_id() << "," << "post async " << std::endl;
        });
        other_thread.join();

        // 没有任务就返回
        int ret = uv_run(&_uv_loop, UV_RUN_DEFAULT);  
        //int ret = uv_run(&_uv_loop, UV_RUN_ONCE);
        //int ret = uv_run(&_uv_loop, UV_RUN_ONCE);
        ret = 1;
    }
    void stop();
    void close();
protected:
    uv_loop_t _uv_loop;
};

class UvHandle
{
public:

protected:
    virtual uv_handle_t* get_uv_handler() = 0;
};
class UvPollHandle
{
protected:
    uv_poll_t* _uv_poll;
};
/**
 * @brief 
 *   投递到一个线程池里边去执行了
 */
class UvWorkHandle
{
        // for(int32_t idx = 0; idx < 9; ++idx)
        // {
        //     uv_work_t* uv_work_ptr = new uv_work_t;
        //     memset(uv_work_ptr, 0, sizeof(uv_work_t));
        //     fib将在线程池执行，after_fib在loop线程执行
        //     uv_queue_work(&_uv_loop, uv_work_ptr, fib, after_fib);
        // }
protected:
    uv_work_t* _uv_work;
};
class UvAsyncHandle
{
protected:
    uv_async_t* _uv_async;
};
class UvStreamHandle
{
protected:
    uv_stream_t* _uv_stream;
};


// class EventLoopSelect;
// class EventLoopIocp;
// class EventLoopEpoll;
// class EventLoopKQueue;
// class EventLoopLibuv;

class NetContext;

int main()
{
    std::cout << "thread_id=" << std::this_thread::get_id() << "," << __FUNCTION__ << std::endl;
    UvEventLoop event_loop;
    event_loop.create();
    event_loop.run();

    return 0;
}


// 最后使用libv封装类似redis aenet框架出来,queue可以有mutex+contition实现或iocp或pile,如何集成curl的需要分析
// nginx 的事件模块也值得参考
/*
uv_loop_t: 事件循环对象
uv_handle_t: 所有句柄的基类
uv_dir_t: 目录句柄
uv_stream_t: 流句柄
uv_tcp_t
uv_udp_t
uv_pipe_t
uv_tty_t
uv_poll_t: 轮询器句柄,用户监控OS本地句柄事件
uv_timer_t: 
uv_prepare_t: 每次轮询之前回调的句柄
uv_check_t: 每次轮询之前后调的句柄
uv_idle_t: 在uv_prepare_t回调的句柄，可能是出现一次pull无任何事件发生
uv_async_t: 应该是线程切换队列的句柄
uv_process_t: 将会新建一个新的进程并且能够允许用户控制该进程并使用流去建立通信通道。
uv_fs_event_t
uv_fs_poll_t: 用于在不执行poll文件句柄的系统上自己实现poll？
uv_signal_t
uv_req_t: 请求句柄基类
uv_getaddrinfo_t: 异步请求目标地址
uv_getnameinfo_t
uv_shutdown_t: shutdown请求
uv_write_t: 
uv_connect_t
uv_udp_send_t
uv_fs_t
uv_work_t: 工作队列回调
uv__io_t: 抽象平台相关的的I/O事件监听器
uv_once_t: 保证代码段只会执行一次的锁



iocp_poll.c
iocp关键函数：
CreateIoCompletionPort: 创建IOCP端口或吧句柄和IOCP端口关联
PostQueuedCompletionStatus: 
GetQueuedCompletionStatus: 
SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0): 设置句柄不被继承

loop初始化的时候会初始化IOCP，EPOLL也是在loop初始化同时初始化epoll
创建tcp_socket的时候会绑定到完成端口


工作队列：
uv_queue_work

时钟：
loop中记录了上次的的时钟
uv__hrtime
    windows: QueryPerformanceCounter
    posix: clock_gettime
    linux: clock_gettime
    darwin: mach_continuous_time
*/

/**
 * 
https://github.com/vpetrigo/caches/blob/master/include/lru_cache_policy.hpp
https://github.com/374576114/cache/blob/master/lib/lirs.h
https://github.com/facebook/CacheLib

template <typename TKey, typename TValue>
struct LRUElement
{
    typedef LRUElement<TKey, TValue> self_type;
    self_type* prev;
    self_type* next;
    TKey key;
    TValue value;
};

// 还可以添加TThreadModel 和各种callback
template <typename TKey, typename TValue>
class LRUCache
{
    typedef LRUElement<TKey, TValue> element_type;
public:
    void put(const TKey& key, TValue& value);
    void remove(const TKey& key);
    TValue& get(const TKey& key);
    // 添加try_get，避免找不到的时候返回值设计复杂，可以返回pair，或者使用输出参数返回
    void update(const TKey& key, const std::function<void(TValue&)>& updater);
    bool exists(const TKey& key);
    //std::list<TValue> range(const std::function<bool(const TValue&)>& filter);
    std::size_t len();
    std::size_t capacity();
    void refresh(element_type* element);
    element_type* head();
    element_type* tail();

protected:
    std::size_t _capatity;
    std::map<TKey, TValue> _cache_map;
    element_type* _head;
    element_type* _tail;
    // 可以用map+list完成，map存放list的element可以优化掉一次list查询
};

class CachePolicy

 */